const SHOW = `@@DVA_LOADING/SHOW`
const HIDE = `@@DVA_LOADING/HIDE`

export default function (opts = {}) {
    const { namespace } = Object.assign({}, {
        namespace: 'loading', // 挂载状态的名字
        only: [], // 只处理那些模型
        except: [] // 不包含那些模型
    }, opts)

    const initialState = {
        global: false,
        models: {},
        effects: {}
    }

    function reducer(state = initialState, { type, payload }) {
        // {payload:{namespace:'模型的命名空间', actionType: "counter/asyncDecrease"}}
        const { namespace, actionType } = payload || {}
        switch (type) {
            case SHOW:
                return {
                    global: true,
                    models: {
                        ...state.models, // 保留其他模型的加载状态
                        [namespace]: true
                    },
                    effects: {
                        ...state.effects, // 保留其他模型的effects
                        [actionType]: true
                    }
                }
            case HIDE:
                const models = { ...state.models, [namespace]: false }
                const effects = { ...state.effects, [actionType]: false }
                const global = Object.values(models).some(m => m)
                return { global, models, effects }
            default:
                return state
        }
    }

    // 当副作用发生的时候
    function onEffect(oldEffect, sagaEffect, model, actionType) {
        const { put } = sagaEffect
        const { namespace } = model
        return function* (action) {
            yield put({ type: SHOW, payload: { namespace, actionType } })
            yield oldEffect(action)
            yield put({ type: HIDE, payload: { namespace, actionType } })
        }
    }

    return {
        onEffect,
        extraReducers: {
            [namespace]: reducer
        }
    }
}